Skip to content

feat(plotnine): implement stem-basic#5636

Merged
MarkusNeusinger merged 4 commits intomainfrom
implementation/stem-basic/plotnine
Apr 30, 2026
Merged

feat(plotnine): implement stem-basic#5636
MarkusNeusinger merged 4 commits intomainfrom
implementation/stem-basic/plotnine

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: stem-basic - python/plotnine

Implements the python/plotnine version of stem-basic.

File: plots/stem-basic/implementations/python/plotnine.py

Parent Issue: #972


🤖 impl-generate workflow

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 30, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The plot displays a damped sinusoidal discrete signal on a warm off-white #FAF8F1 background. Vertical stems in #009E73 extend from the prominent dark horizontal baseline at y=0 to circular markers of the same color. 30 sample points are plotted across x=[0,29] with amplitude ranging from ~1.0 down to near-zero. The title "stem-basic · plotnine · anyplot.ai" is clearly rendered in dark ink at the top. Axis labels "Sample Index" (x) and "Amplitude" (y) are readable in dark ink. Subtle horizontal grid lines are visible. No top/right spines. All text is fully readable against the light background.

Dark render (plot-dark.png): Same composition on a near-black #1A1A17 background. The stems and markers remain identical #009E73 — data colors are unchanged from the light render. The title, axis labels, and tick labels flip to light/off-white text and are clearly readable against the dark background. The y=0 baseline appears as a light-gray horizontal rule. No dark-on-dark failures detected; all text passes legibility against the dark surface.

Both paragraphs are required. A review that only describes one render is invalid.

Score: 87/100

Category Score Max
Visual Quality 29 30
Design Excellence 10 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 8 10
Total 87 100

Visual Quality (29/30)

  • VQ-01: Text Legibility (8/8) — Title 24pt, axis labels 20pt, tick labels 16pt, all explicitly set and readable in both themes
  • VQ-02: No Overlap (6/6) — No overlapping elements
  • VQ-03: Element Visibility (6/6) — Stems and markers well-sized for 30 data points
  • VQ-04: Color Accessibility (2/2) — Single-series #009E73, CVD-safe, good contrast on both surfaces
  • VQ-05: Layout & Canvas (4/4) — Good proportions, balanced margins, data fills canvas well
  • VQ-06: Axis Labels & Title (1/2) — "Amplitude" and "Sample Index" are descriptive but lack units (e.g., "Amplitude (normalized)" or "Amplitude (a.u.)")
  • VQ-07: Palette Compliance (2/2) — First series #009E73, backgrounds #FAF8F1/#1A1A17, theme-adaptive chrome correct in both renders

Design Excellence (10/20)

  • DE-01: Aesthetic Sophistication (4/8) — Clean, professional single-color composition using the brand green. Well-configured but does not rise above a polished library default — no intentional hierarchy, size variation, or layered visual emphasis.
  • DE-02: Visual Refinement (4/6) — Good deliberate choices: x-grid removed, y-grid at 10% opacity, axis lines in INK_SOFT, theme_minimal base removes top/right spines. Lacks the final polish to reach "every detail perfect."
  • DE-03: Data Storytelling (2/6) — The damped sinusoidal data choice is excellent and scientifically relevant, but the visualization design offers no visual hierarchy: all stems and markers are identical size and color regardless of amplitude magnitude. The viewer must discover the damping story themselves without any emphasis guiding them there.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct stem plot via geom_segment + geom_point + geom_hline
  • SC-02: Required Features (4/4) — Thin vertical stems, visible circular markers, y=0 baseline, consistent sizing throughout
  • SC-03: Data Mapping (3/3) — Sample index on x, amplitude on y, all 30 points visible
  • SC-04: Title & Legend (3/3) — "stem-basic · plotnine · anyplot.ai" correct; no legend needed for single series

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows both positive and negative values, demonstrates the discrete nature of stem plots, amplitude variation across the full range
  • DQ-02: Realistic Context (5/5) — Damped sinusoidal signal is a canonical signal-processing example; neutral, scientific, and directly relevant to stem plot use cases
  • DQ-03: Appropriate Scale (4/4) — Values in [-0.65, 1.0], 30 samples within the spec's 10–100 recommended range, physically plausible decay constant

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Clean linear structure: imports → constants → data → plot → save
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set
  • CQ-03: Clean Imports (2/2) — All imported symbols are used
  • CQ-04: Code Elegance (2/2) — Pythonic, appropriate complexity, no over-engineering
  • CQ-05: Output & API (1/1) — Saves as plot-{THEME}.png, verbose=False, current API

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (5/5) — Expert use of ggplot grammar: ggplot() + geom_* + labs() + theme() pipeline, correct aes() mapping, proper theme composition
  • LM-02: Distinctive Features (3/5) — The layered composition (geom_hline + geom_segment + geom_point) to construct a stem plot from primitives is genuinely grammar-of-graphics thinking. However, no plotnine-exclusive feature (e.g., stat_*, faceting, scale_*_manual for emphasis) is used to go beyond what any ggplot2 port would produce.

Score Caps Applied

  • None — no caps triggered (all threshold conditions at 0 were avoided)

Strengths

  • Perfect spec compliance: all stem plot requirements met with the correct primitive combination
  • Excellent data choice: damped sinusoidal signal is the textbook stem plot use case
  • Flawless theme adaptation: both light and dark renders are readable with correct backgrounds and chrome
  • Code quality is exemplary: clean, reproducible, idiomatic plotnine throughout

Weaknesses

  • DE-03 LOW: No visual hierarchy or emphasis through design — all stems identical despite amplitude varying from 1.0 to near-zero. Visual storytelling opportunity missed (e.g., marker size proportional to |amplitude|, or color intensity fading with amplitude to reinforce the decay pattern)
  • VQ-06 minor: Axis labels lack units — "Amplitude (normalized)" would score full points
  • DE-01 MODERATE: Single-color flat design is clean but not sophisticated — no intentional emphasis, size variation, or focal point hierarchy

Issues Found

  1. DE-03 LOW (2/6): Uniform stem/marker appearance gives no visual cue about the damping story.
    • Fix: Scale geom_point marker size with |signal| (e.g., size = 3 + 6 * abs(signal)) OR use alpha proportional to amplitude — let the decay be visible in the marker design, not just inferred from stem height.
  2. VQ-06 (1/2): "Amplitude" axis label missing units.
    • Fix: Change to y="Amplitude (normalized)" or y="Amplitude (a.u.)" in labs().
  3. DE-01 MODERATE (4/8): Design lacks intentional hierarchy.
    • Fix: Combine the marker-size-encodes-amplitude approach above, and consider making the baseline a slightly thicker/brighter line to anchor the composition as the zero-crossing reference.

AI Feedback for Next Attempt

Key improvement: encode visual meaning into the marker design. Use aes(size=abs(signal)) in geom_point with scale_size_continuous(range=(2, 7), guide=False) to make the damping visible through marker size — this turns a flat data display into a design that tells the decay story. Also add units to the y-axis label ("Amplitude (normalized)") and consider slightly thickening the geom_hline baseline (size=1.2) to make the zero-crossing reference more prominent. These changes primarily lift DE-03 from 2 to 4+ and push the total above 90.

Verdict: REJECTED

@github-actions github-actions Bot added quality:87 Quality score 87/100 ai-rejected Quality not OK, triggers update labels Apr 30, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Apr 30, 2026
@github-actions
Copy link
Copy Markdown
Contributor Author

🔧 Repair Attempt 1/4

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 30, 2026

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): The plot renders on a warm off-white #FAF8F1 background. A damped sinusoidal discrete signal is displayed as 30 stems in brand green #009E73, with thin vertical lines from the y=0 baseline to filled circle markers at each sample value. The baseline itself is drawn as a slightly darker horizontal line at y=0. Title "stem-basic · plotnine · anyplot.ai" is displayed in dark #1A1A17 text at the top center. X-axis label "Sample Index" and y-axis label "Amplitude" are in dark ink, clearly readable. Tick labels are in muted #4A4A44. A subtle horizontal grid (y-axis only) is barely visible at ~10% opacity. No legend (single series, correctly omitted). All text is clearly readable against the light background — no legibility issues. Legibility verdict: PASS.

Dark render (plot-dark.png): The same plot renders on a near-black #1A1A17 background. Data colors are identical to the light render — stems and markers remain #009E73, confirming only chrome flips. Title and axis labels are in light #F0EFE8 text, clearly visible against the dark surface. Tick labels appear in muted #B8B7B0. The baseline is rendered in a lighter tone, visible against the dark background. Grid lines remain extremely subtle. No dark-on-dark text failures observed — all labels and titles are fully legible. Legibility verdict: PASS.

Both renders are theme-correct with identical data colors and properly adaptive chrome.

Score: 87/100

Category Score Max
Visual Quality 29 30
Design Excellence 10 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 8 10
Total 87 100

Visual Quality (29/30)

  • VQ-01: Text Legibility (8/8) - Title 24pt, axis labels 20pt, tick labels 16pt — all explicitly set and readable in both themes
  • VQ-02: No Overlap (6/6) - 30 well-spaced stems, no text collisions
  • VQ-03: Element Visibility (6/6) - Stems (size=0.9) and markers (size=4) appropriately sized for 30 points; baseline clearly visible
  • VQ-04: Color Accessibility (2/2) - Single brand green #009E73, CVD-safe, good contrast in both themes
  • VQ-05: Layout & Canvas (4/4) - 16:9 canvas, balanced margins, plot fills canvas well
  • VQ-06: Axis Labels & Title (1/2) - Y-axis "Amplitude" is descriptive but lacks units/context ("Amplitude (normalized)" would score full points)
  • VQ-07: Palette Compliance (2/2) - First (and only) series is #009E73; backgrounds are #FAF8F1 (light) and #1A1A17 (dark); theme chrome adapts correctly

Design Excellence (10/20)

  • DE-01: Aesthetic Sophistication (4/8) - Clean, well-configured implementation with brand color and appropriate baseline; not generic, but not publication-ready
  • DE-02: Visual Refinement (4/6) - Y-axis-only grid at 10% opacity is an excellent choice; x-axis grid suppressed; theme_minimal() removes top/right spines; genuinely refined
  • DE-03: Data Storytelling (2/6) - Damped sinusoidal is a compelling data choice but the visualization doesn't use visual hierarchy or emphasis to guide the viewer toward the decay narrative

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) - Correct stem plot via geom_segment + geom_point + geom_hline
  • SC-02: Required Features (4/4) - Thin stems from baseline, visible circular markers, y=0 baseline, consistent sizing throughout
  • SC-03: Data Mapping (3/3) - Sample index on x, amplitude on y; all 30 points visible
  • SC-04: Title & Legend (3/3) - "stem-basic · plotnine · anyplot.ai" correct; no legend (appropriate for single series)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) - Shows positive AND negative values, oscillation, and decay envelope — demonstrates all stem plot characteristics
  • DQ-02: Realistic Context (5/5) - Damped sinusoidal signal is a textbook signal processing example; neutral, scientific, comprehensible
  • DQ-03: Appropriate Scale (4/4) - 30 samples, normalized amplitude range, physically plausible decay constant and frequency

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) - Clean Imports → Data → Plot → Save structure; no functions or classes
  • CQ-02: Reproducibility (2/2) - np.random.seed(42) set
  • CQ-03: Clean Imports (2/2) - All 11 plotnine imports are used
  • CQ-04: Code Elegance (2/2) - Pythonic, appropriate complexity, no over-engineering
  • CQ-05: Output & API (1/1) - Saves as plot-{THEME}.png, current API throughout

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (5/5) - Fully idiomatic grammar of graphics: layered geoms, aes() mappings, theme() customization
  • LM-02: Distinctive Features (3/5) - Composing a stem plot from primitive geoms (geom_segment + geom_point + geom_hline) is distinctively plotnine — no stem() function exists, so this shows grammar-of-graphics thinking; somewhat library-specific but not exceptional

Score Caps Applied

  • None

Strengths

  • Perfect spec compliance: all stem plot features (stems, markers, baseline) implemented correctly using plotnine's grammar of graphics
  • Excellent theme adaptation: both renders are fully legible with correct backgrounds, text colors, and grid tokens
  • Compelling realistic data: damped sinusoidal signal is a natural fit for a stem plot and shows positive/negative values with amplitude decay
  • Refined grid design: y-axis-only grid at 10% opacity is an excellent visual choice

Weaknesses

  • Y-axis label "Amplitude" lacks context; "Amplitude (normalized)" would be more informative
  • No visual storytelling or hierarchy — the decay pattern is interesting but nothing in the design emphasizes it

Issues Found

  1. VQ-06 LOW: Y-axis label "Amplitude" is descriptive but without units/context
    • Fix: Change to y="Amplitude (normalized)" in labs()
  2. DE-03 LOW: Data is displayed but not interpreted — the decay narrative isn't visually emphasized
    • Fix: Consider varying stem alpha or using a subtle annotation/arrow to highlight the decay envelope, or draw the theoretical decay curve as a faint reference line

AI Feedback for Next Attempt

Rename y-axis to "Amplitude (normalized)". For design storytelling, add a faint exponential decay envelope curve overlaid on the stems (using geom_line with low alpha) to visually explain the damped sinusoidal pattern — this would elevate DE-03 from default to guided narrative without cluttering the plot.

Verdict: APPROVED

@github-actions github-actions Bot added the ai-approved Quality OK, ready for merge label Apr 30, 2026
@MarkusNeusinger MarkusNeusinger merged commit 5c778f5 into main Apr 30, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/stem-basic/plotnine branch April 30, 2026 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-approved Quality OK, ready for merge ai-attempt-1 First repair attempt quality:87 Quality score 87/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant